/**
 * AI计算Web Worker
 * 处理路径查找、行为分析等重计算任务
 */

// 导入必要的工具类
importScripts('../utils/Vector2D.js');

class WorkerPathFinder {
    constructor(gridSize = 20) {
        this.gridSize = gridSize;
        this.grid = null;
        this.width = 0;
        this.height = 0;
    }

    initializeGrid(mapWidth, mapHeight, buildings) {
        this.width = Math.ceil(mapWidth / this.gridSize);
        this.height = Math.ceil(mapHeight / this.gridSize);
        this.grid = [];

        for (let x = 0; x < this.width; x++) {
            this.grid[x] = [];
            for (let y = 0; y < this.height; y++) {
                this.grid[x][y] = { walkable: true, cost: 1 };
            }
        }

        for (const building of buildings) {
            const startX = Math.floor(building.position.x / this.gridSize);
            const startY = Math.floor(building.position.y / this.gridSize);
            const endX = Math.ceil((building.position.x + building.size.x) / this.gridSize);
            const endY = Math.ceil((building.position.y + building.size.y) / this.gridSize);

            for (let x = Math.max(0, startX - 1); x <= Math.min(this.width - 1, endX + 1); x++) {
                for (let y = Math.max(0, startY - 1); y <= Math.min(this.height - 1, endY + 1); y++) {
                    if (x >= startX && x < endX && y >= startY && y < endY) {
                        this.grid[x][y].walkable = false;
                    } else {
                        this.grid[x][y].cost = 3;
                    }
                }
            }
        }
    }

    findPath(startPos, endPos) {
        const start = {
            x: Math.floor(startPos.x / this.gridSize),
            y: Math.floor(startPos.y / this.gridSize)
        };
        const end = {
            x: Math.floor(endPos.x / this.gridSize),
            y: Math.floor(endPos.y / this.gridSize)
        };

        if (!this.isValidPosition(start) || !this.isValidPosition(end)) {
            return null;
        }

        const openSet = [start];
        const closedSet = new Set();
        const cameFrom = new Map();
        const gScore = new Map();
        const fScore = new Map();

        gScore.set(this.posKey(start), 0);
        fScore.set(this.posKey(start), this.heuristic(start, end));

        while (openSet.length > 0) {
            let current = openSet.reduce((min, pos) => 
                fScore.get(this.posKey(pos)) < fScore.get(this.posKey(min)) ? pos : min
            );

            if (current.x === end.x && current.y === end.y) {
                return this.reconstructPath(cameFrom, current);
            }

            openSet.splice(openSet.indexOf(current), 1);
            closedSet.add(this.posKey(current));

            for (const neighbor of this.getNeighbors(current)) {
                if (closedSet.has(this.posKey(neighbor)) || !this.grid[neighbor.x][neighbor.y].walkable) {
                    continue;
                }

                const tentativeGScore = gScore.get(this.posKey(current)) + this.grid[neighbor.x][neighbor.y].cost;

                if (!openSet.some(pos => pos.x === neighbor.x && pos.y === neighbor.y)) {
                    openSet.push(neighbor);
                } else if (tentativeGScore >= gScore.get(this.posKey(neighbor))) {
                    continue;
                }

                cameFrom.set(this.posKey(neighbor), current);
                gScore.set(this.posKey(neighbor), tentativeGScore);
                fScore.set(this.posKey(neighbor), tentativeGScore + this.heuristic(neighbor, end));
            }
        }

        return null;
    }

    posKey(pos) {
        return `${pos.x},${pos.y}`;
    }

    heuristic(a, b) {
        return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
    }

    getNeighbors(pos) {
        const neighbors = [];
        const directions = [
            {x: 0, y: 1}, {x: 1, y: 0}, {x: 0, y: -1}, {x: -1, y: 0},
            {x: 1, y: 1}, {x: 1, y: -1}, {x: -1, y: 1}, {x: -1, y: -1}
        ];

        for (const dir of directions) {
            const neighbor = {x: pos.x + dir.x, y: pos.y + dir.y};
            if (this.isValidPosition(neighbor)) {
                neighbors.push(neighbor);
            }
        }

        return neighbors;
    }

    isValidPosition(pos) {
        return pos.x >= 0 && pos.x < this.width && pos.y >= 0 && pos.y < this.height;
    }

    reconstructPath(cameFrom, current) {
        const path = [current];
        while (cameFrom.has(this.posKey(current))) {
            current = cameFrom.get(this.posKey(current));
            path.unshift(current);
        }
        
        return path.map(pos => ({
            x: pos.x * this.gridSize + this.gridSize / 2,
            y: pos.y * this.gridSize + this.gridSize / 2
        }));
    }
}

// Worker全局变量
const pathFinder = new WorkerPathFinder();
const aiTasks = new Map();

// 消息处理
self.onmessage = function(e) {
    const { type, id, data } = e.data;
    
    try {
        switch (type) {
            case 'initGrid':
                pathFinder.initializeGrid(data.width, data.height, data.buildings);
                self.postMessage({ type: 'gridInitialized', id });
                break;
                
            case 'findPath':
                const path = pathFinder.findPath(data.start, data.end);
                self.postMessage({ 
                    type: 'pathFound', 
                    id, 
                    data: { path, tankId: data.tankId } 
                });
                break;
                
            case 'analyzePlayerBehavior':
                const patterns = analyzePlayerBehavior(data.history);
                self.postMessage({ 
                    type: 'behaviorAnalyzed', 
                    id, 
                    data: { patterns, tankId: data.tankId } 
                });
                break;
                
            case 'calculateOptimalStrategy':
                const strategy = calculateOptimalStrategy(data.distance, data.playerBehavior, data.teamStatus);
                self.postMessage({ 
                    type: 'strategyCalculated', 
                    id, 
                    data: { strategy, tankId: data.tankId } 
                });
                break;
                
            default:
                console.warn('Unknown worker task type:', type);
        }
    } catch (error) {
        self.postMessage({ 
            type: 'error', 
            id, 
            error: error.message 
        });
    }
};

function analyzePlayerBehavior(history) {
    const patterns = {
        aggressive: 0,
        defensive: 0,
        mobile: 0,
        camping: 0
    };

    if (history.length < 10) return patterns;

    let totalMovement = 0;
    let directionChanges = 0;
    let avgSpeed = 0;

    for (let i = 1; i < history.length; i++) {
        const movement = Math.sqrt(
            Math.pow(history[i].position.x - history[i-1].position.x, 2) +
            Math.pow(history[i].position.y - history[i-1].position.y, 2)
        );
        totalMovement += movement;
        avgSpeed += movement;

        if (i > 1) {
            const angle1 = Math.atan2(
                history[i].position.y - history[i-1].position.y,
                history[i].position.x - history[i-1].position.x
            );
            const angle2 = Math.atan2(
                history[i-1].position.y - history[i-2].position.y,
                history[i-1].position.x - history[i-2].position.x
            );
            if (Math.abs(angle1 - angle2) > Math.PI / 4) {
                directionChanges++;
            }
        }
    }

    avgSpeed /= history.length;
    
    patterns.mobile = Math.min(1, avgSpeed / 5);
    patterns.camping = 1 - patterns.mobile;
    patterns.aggressive = Math.min(1, directionChanges / (history.length / 3));
    patterns.defensive = 1 - patterns.aggressive;

    return patterns;
}

function calculateOptimalStrategy(distance, playerBehavior, teamStatus) {
    let strategy = 'balanced';
    
    if (distance < 150) {
        if (playerBehavior.aggressive > 0.6) {
            strategy = 'retreat_and_flank';
        } else {
            strategy = 'aggressive_assault';
        }
    } else if (distance < 300) {
        if (playerBehavior.mobile > 0.7) {
            strategy = 'prediction_shot';
        } else {
            strategy = 'advance_and_shoot';
        }
    } else {
        if (teamStatus.allies > 1) {
            strategy = 'coordinate_attack';
        } else {
            strategy = 'long_range_harass';
        }
    }

    return strategy;
} 